/*
 * @Author: yanjikun
 * @Date: 2022-05-19 14:52:51
 * @LastEditors: yanjikun
 * @LastEditTime: 2022-05-19 17:00:20
 * @Description: file content
 */
import SockJS from 'sockjs-client/dist/sockjs.min.js'
import Stomp, { Client, Subscription } from 'webstomp-client'
import { Observable, type Subscriber } from 'rxjs'
import { storage } from '../Storage'
import { TENANT } from '@/enums/cacheEnums'
import { isNull } from '../is'
export default class TrackerService {
  stompClient: Client | null = null
  subscriber: Subscription | null = null
  connectedPromise: ((value: unknown) => void) | null = null
  listenerObserver: Subscriber<any> | null = null
  alreadyConnectedOnce = false
  connection: Promise<any> | null = null
  listener: Observable<any>
  constructor() {
    this.connection = this.createConnection()
    this.listener = this.createListener()
  }

  connect(errorFunction = () => {}) {
    if (this.connectedPromise === null) {
      this.connection = this.createConnection()
    }
    const authToken =
      localStorage.getItem('jhi-authenticationToken') ||
      sessionStorage.getItem('jhi-authenticationToken')
    let url = `${
      import.meta.env.MODE === 'production'
        ? window.location.origin
        : import.meta.env.VITE_APP_BASE_URL
    }/websocket/topic${authToken ? `?access_token=${authToken}` : ''}`
    const socket = new SockJS(url, null, { timeout: 15000 })
    this.stompClient = Stomp.over(socket, { protocols: ['v12.stomp'] })
    const headers = {}
    return new Promise<void>((resolve, reject) => {
      this.stompClient?.connect(
        headers,
        () => {
          this.afterConnect()
          resolve()
        },
        () => {
          reject()
          setTimeout(() => {
            errorFunction()
          }, 3000)
        },
      )
    })
  }

  afterConnect() {
    this.connectedPromise!('success')
    this.connectedPromise = null
    //this.sendActivity();
    if (!this.alreadyConnectedOnce) {
      // this.sendActivity();
      // this.router.afterEach(() => this.sendActivity());
      this.alreadyConnectedOnce = true
    }
  }

  disconnect() {
    if (!isNull(this.stompClient)) {
      this.stompClient.disconnect()
      this.stompClient = null
    }
    this.alreadyConnectedOnce = false
  }

  receive() {
    return this.listener
  }

  sendActivity() {
    if (!isNull(this.stompClient) && this.stompClient.connected) {
      this.stompClient.send(
        '/topic/activity', // destination
        JSON.stringify(undefined), // body
        {}, // header
      )
    }
  }

  subscribe() {
    this.connection!.then(() => {
      const tenant = storage.get(TENANT)
      this.subscriber = this.stompClient!.subscribe(`/topic/tracker/${tenant}`, (data) => {
        ///${store.getters.Tenant}
        try {
          this.listenerObserver!.next(JSON.parse(data.body))
        } catch (error) {
          console.log(error)
        }
      })
    })
  }

  unsubscribe() {
    if (this.subscriber !== null) {
      this.subscriber.unsubscribe()
    }
    this.listener = this.createListener()
  }

  createListener() {
    return new Observable((observer) => {
      this.listenerObserver = observer
    })
  }

  createConnection() {
    return new Promise((resolve) => (this.connectedPromise = resolve))
  }
}
